import React, {memo, useEffect, useRef, useState} from 'react';
import {useDispatch, useSelector} from "react-redux";

import "./meltCurve.css";
import PlateTable from "../../../../../components/plateTable/PlateTable";
import Title from "../../../../../components/Title/Title";
import {FluorescenceCanvas, FluorescenceEntity} from "../../../../../common/canvas";
import {WELLS_COLUMN, WELLS_ROW} from "../../../plate/config";
import {deepClone} from "../../../../../common/utils";
import {saveTargetSelectedArr} from "../quantification/store/actionCreators";
import {saveAnalysisShowLineArr} from "../../../plate/store/actionCreators";
import {saveData} from "../../../store/actionCreators";
import {MELT} from "../../../protocol/config";
import {saveExportObj, saveExportObjCn} from "../../../export/store/actionCreators";
import TwoPeakFlagTable from "../../../../../components/twoPeakFlagTable/TwoPeakFlagTable";

export default memo(function Quantification() {
  const dispatch = useDispatch();
  const {data, meltGrad, analysisShowLineArr, targetSelectedArr, exportObj, exportObjCn, isCN} = useSelector(state => ({
    data: state.dataReducer.data,
    analysisShowLineArr: state.plateReducer.analysisShowLineArr,  //  包含可以画线的well(同时有target和sampleName)
    targetSelectedArr: state.quantificationReducer.targetSelectedArr, //  可以显示的target
    exportObj: state.exportReducer.exportObj,
    exportObjCn: state.exportReducer.exportObjCn,
    meltGrad: state.protocolReducer.meltGrad,
    isCN: state.languageReducer.isCN
  }));
  const [target, setTarget] = useState([]);  //  target条目
  const [showMoreData, setShowMoreData] = useState(false); //  显示More Data
  const [curveAutoAxes, setCurveAutoAxes] = useState(true);
  const [peakAutoAxes, setPeakAutoAxes] = useState(true);
  const [curveMinY, setCurveMinY] = useState(0);
  const [curveMaxY, setCurveMaxY] = useState(Infinity);
  const [peakMinY, setPeakMinY] = useState(0);
  const [peakMaxY, setPeakMaxY] = useState(Infinity);
  const [wellId, setWellId] = useState([]);  //  选中well的target
  const [lineId, setLineId] = useState(-1);  //  选中的线的ID,选中表格条目也会改变此ID
  const [toggleRFU, setToggleRFU] = useState(true);  //  切换RFU Melt
  const meltMessageTable = useRef();
  const moreDataMessageTable = useRef();
  const [moreDataTableTitle, setMoreDataTableTitle] = useState([]);
  const [isMessageTableEnter, setIsMessageTableEnter] = useState(false);
  let cloneTarget = [];
  let cloneTargetSelectedArr = [];
  let cloneAnalysisShowLineArr = [];
  let cloneData = {};
  const meltStep = data.protocol.stages.filter(item => item.state === MELT)[0];
  const commonStyle = {
    paddingLeft: 80,
    paddingTop: 10,
    paddingBottom: 50,
    paddingRight: 10,
    dataPaddingLeft: 40,
    dataPaddingBottom: 40,
    dataPaddingTop: 40,
    dataPaddingRight: 40,
    axisTitleBottom: isCN ? "温度" : "Temperature,Celsius",
    axisTitleBottomPadding: 20,
    minX: meltStep ? meltStep.steps[0].temperature : 60,
    maxX: meltStep ? meltStep.steps[1].temperature : 95,
    xDataStart: meltStep ? meltStep.steps[0].temperature : 60,
    xDataGradient: meltStep ? meltStep.steps[0].gradient : 0.5
  };
  const curveStyle = {
    axisTitleLeft: "RFU(10^3)",
    axisTitleLeftPadding: 50
  };
  const peakStyle = {
    axisTitleLeft: "-d(RFU)/dT",
    axisTitleLeftPadding: 50
  };

  useEffect(() => {
    if (showMoreData) {
      return;
    }
    const meltCurve = FluorescenceCanvas.init("meltCurve", {...commonStyle, ...curveStyle}),
      meltPeak = FluorescenceCanvas.init("meltPeak", {...commonStyle, ...peakStyle});
    // console.log(meltGrad);
    // console.log(analysisShowLineArr);
    meltCurve.setMinX(meltGrad.minX);
    meltCurve.setMaxX(meltGrad.maxX);
    meltPeak.setMinX(meltGrad.minX);
    meltPeak.setMaxX(meltGrad.maxX);
    if (!curveAutoAxes) {        //  取消curveAutoAxes后重置相应的属性
      meltCurve.setAutoAxisY(false);
      meltCurve.setMaxY(curveMaxY);
      meltCurve.setMinY(curveMinY);
    }
    if (!peakAutoAxes) {        //  取消peakAutoAxes后重置相应的属性
      meltPeak.setAutoAxisY(false);
      meltPeak.setMaxY(curveMaxY);
      meltPeak.setMinY(curveMinY);
    }
    analysisShowLineArr.forEach(item => {
      if (item.omit.value === "true" || !data.wells[item.id].show || !targetSelectedArr.includes(item.target.value)) {
        return;
      }
      const meltCurveData = data.wells[item.id].meltData,
        meltPeakData = data.wells[item.id].meltPeak;
      meltCurve.addEntity(FluorescenceEntity.getInstance({
        id: item.id,
        dataList: meltCurveData,
        color: item.color,
        highlight: item.id === Number(wellId),
        text: WELLS_ROW[item.row] + WELLS_COLUMN[item.col]
      }));
      meltPeak.addEntity(FluorescenceEntity.getInstance({
        id: item.id,
        dataList: meltPeakData,
        color: item.color,
        highlight: item.id === Number(wellId),
        text: WELLS_ROW[item.row] + WELLS_COLUMN[item.col]
      }));
    });
    meltCurve.onMousemove(function () {
      this && setLineId(this.id);
    });
    meltPeak.onMousemove(function () {
      this && setLineId(this.id);
    });
    // 设置Export对象
    setTimeout(() => {
      let cloneExportObj = {};
      cloneExportObj = deepClone(isCN ? exportObjCn : exportObj, cloneExportObj);
      cloneExportObj.analysis.imgMeltCurve = document.getElementById("meltCurveImgUrl").toDataURL().split(",")[1];
      cloneExportObj.analysis.imgMeltPeak = document.getElementById("meltPeakImgUrl").toDataURL().split(",")[1];
      isCN ? dispatch(saveExportObjCn(cloneExportObj))
        : dispatch(saveExportObj(cloneExportObj));
    });
    return () => {
      meltCurve.destroyCanvas();
      meltPeak.destroyCanvas();
    };
  }, [data, meltGrad, analysisShowLineArr, targetSelectedArr, showMoreData, curveMinY, curveMaxY, curveAutoAxes, peakMinY, peakMaxY, peakAutoAxes, wellId]);

  useEffect(() => {
    let targetMap = new Map(),
      dataTarget = [];
    data.wells.forEach(item => item.targets.forEach(item_ => targetMap.set(item_.name, {...item_, opt: targetSelectedArr.includes(item_.name)})));
    targetMap.forEach(value => dataTarget.push(value));
    setTarget(dataTarget);

    //  设置moreDataTable表头
    let start = 0, end = 0, gradient = 0, result = [];
    data.protocol.stages.forEach(item => {
      if (item.state === MELT) {
        start = item.steps[0].temperature;
        end = item.steps[1].temperature;
        gradient = item.steps[0].gradient;
        while (start <= end) {
          result[result.length] = start;
          start += gradient;
        }
      }
    });
    setMoreDataTableTitle(result);
  }, [data]);

  useEffect(() => { //  点击右下角plate时的联动
    if (showMoreData) {
      return;
    }
    if (isMessageTableEnter) {
      setIsMessageTableEnter(false);
      return;
    }
    if (data.wells[wellId[0]] && data.wells[wellId[0]].targets.length === 0) {
      return;
    }
    let scrollTop = meltMessageTable.current.scrollTop; //  滚动条滚上去的高度
    let wellHeight = analysisShowLineArr.findIndex(item => item.id === Number(wellId[0])) * 38; //  当前元素相对于整个区域的高度(包括隐藏的部分)
    let clientHeight = meltMessageTable.current.clientHeight; //  表格区域可见高度
    if (wellHeight - scrollTop > clientHeight || wellHeight < scrollTop) {
      meltMessageTable.current.scrollTop = wellHeight;  //  控制messageTable表格跳转到指定well
    }
  }, [wellId]);

  /* useEffect(() => { //  点击右下角plate时的联动
   if (showMoreData) {
   //  moreData联动
   let moreDataScrollTop = moreDataMessageTable.current.scrollTop; //  滚动条滚上去的高度
   let moreDataWellHeight = analysisShowLineArr.findIndex(item => item.id === Number(wellId[0])) * 38; //  当前元素相对于整个区域的高度(包括隐藏的部分)
   let moreDataClientHeight = moreDataMessageTable.current.clientHeight; //  表格区域可见高度
   if (moreDataWellHeight - moreDataScrollTop > moreDataClientHeight || moreDataWellHeight < moreDataScrollTop) {
   moreDataMessageTable.current.scrollTop = moreDataWellHeight;  //  控制messageTable表格跳转到指定well
   }
   } else {
   let scrollTop = meltMessageTable.current.scrollTop; //  滚动条滚上去的高度
   let wellHeight = analysisShowLineArr.findIndex(item => item.id === Number(wellId[0])) * 38; //  当前元素相对于整个区域的高度(包括隐藏的部分)
   let clientHeight = meltMessageTable.current.clientHeight; //  表格区域可见高度
   if (wellHeight - scrollTop > clientHeight || wellHeight < scrollTop) {
   meltMessageTable.current.scrollTop = wellHeight;  //  控制messageTable表格跳转到指定well
   }
   }
   }, [wellId]);*/

  //  View Setting点击Opt操作
  function viewSettingSelect(indey) {
    cloneTarget = deepClone(target, cloneTarget);
    cloneTargetSelectedArr = deepClone(targetSelectedArr, cloneTargetSelectedArr);
    cloneTarget[indey].opt = !cloneTarget[indey].opt;
    cloneTargetSelectedArr = cloneTarget.map(item => item.opt && item.name).filter(item => item);
    setTarget(cloneTarget);
    dispatch(saveTargetSelectedArr(cloneTargetSelectedArr));
  }

  //  选择message的某一条
  function messageSelected(indey) {
    setLineId(indey);
    setIsMessageTableEnter(true);
  }

  //  改变Omit
  function changeOmit(value, item_, indey) {
    cloneData = deepClone(data, cloneData);
    cloneAnalysisShowLineArr = deepClone(analysisShowLineArr, cloneAnalysisShowLineArr);
    cloneData.wells.forEach(well => well.selected = false);
    cloneAnalysisShowLineArr[indey].omit.value = String(value);
    cloneData.wells[item_.id].lines[item_.channelIndex].omit = value;
    dispatch(saveAnalysisShowLineArr(cloneAnalysisShowLineArr));
    dispatch(saveData(cloneData));
  }

  // 切换RFU Melt
  function toggleRFUAction() {
    setToggleRFU(!toggleRFU);
  }

  return showMoreData ? (
    <div className="analysisMeltCurve moreData">
      <section className="meltMoreDataTop">
        <div className="meltTableStyle scrollBarStyle moreDataTableStyle" style={{overflow: "hidden", border: "2px solid #213040", borderRadius: 15}}>
          <ul style={{width: 1562}}>
            <li>{isCN ? "反应孔" : "Well"}</li>
            <li>{isCN ? "忽略" : "Omit"}</li>
            <li>{isCN ? "标记" : "Flag"}</li>
            <li>{isCN ? "样品名称" : "Sample"}</li>
            <li>{isCN ? "基因名称" : "Target"}</li>
            <li>{isCN ? "类型" : "Task"}</li>
            <li>{isCN ? "染料" : "Dye"}</li>
            <li>{isCN ? "Tm1" : "Tm1"}</li>
            <li>{isCN ? "Tm1" : "Tm2"}</li>
            <li>{isCN ? "峰值1" : "Peak High1"}</li>
            <li>{isCN ? "峰值2" : "Peak High2"}</li>
          </ul>
          <section className="scrollBarStyle"
                   style={{height: 267}}
                   ref={moreDataMessageTable}
          >
            {
              analysisShowLineArr.map((item, index) => (
                <ul key={item.id + item.target.value}
                    onMouseEnter={() => messageSelected(item.id)}
                    style={{backgroundColor: item.id === wellId[0] ? "#ccc" : null}}
                >
                  <li>{item.well.value}</li>
                  <li className="tableMessageOmit">
                    <input type="checkbox" checked={JSON.parse(item.omit.value)} readOnly={true}/>
                  </li>
                  <li>{item.flag.value}</li>
                  <li>{item.sample.value}</li>
                  <li>{item.target.value}</li>
                  <li>{item.task.value}</li>
                  <li>{item.dye.value}</li>
                  <li>{item.tm1}</li>
                  <li>{item.tm2}</li>
                  <li>{Number(item.peakHigh1).toFixed(3)}</li>
                  <li>{item.peakHigh2}</li>
                </ul>
              ))
            }
          </section>
        </div>
      </section>
      <section className="meltMoreDataBottom">
        <div>
          <div>{isCN ? "双峰标记" : "Two Peak Flag"}</div>
          <TwoPeakFlagTable plateClass="runPagePlateTableMid"
                            setWellId={setWellId}
          />
        </div>
        <div className="meltMoreDataTable">
          <div>
            <div>
              {
                isCN
                  ? toggleRFU ? "熔解曲线相对荧光强度" : "熔解曲线相对荧光强度导数"
                  : toggleRFU ? "RFU Melt" : "Derivative RFU Melt"
              }
            </div>
            <div onClick={toggleRFUAction}>-d(RFU)/dT</div>
          </div>
          <div className="scrollBarStyle">
            <ul style={{zIndex: 999}}>
              <li className="quantificationMoreDataTableLi">
                <div>{isCN ? "温度" : "Temp"}</div>
                <div>{isCN ? "反应孔" : "Well"}</div>
              </li>
              {
                moreDataTableTitle.map((item, index) => (
                  <li key={item}>{(+item).toFixed(2)}</li>
                ))
              }
            </ul>
            {
              analysisShowLineArr.map((line, lineIndex) => (
                <ul key={line.target.value + lineIndex}>
                  <li>{line.well.value}</li>
                  {
                    data.wells[line.id].meltData.map((item, index) => (
                      <li key={line.target.value + item + index}>
                        {
                          toggleRFU
                            ? (+item * 1000).toFixed(3)
                            : Math.log10(+item * 1000).toFixed(3)
                        }
                      </li>
                    ))
                  }
                </ul>
              ))
            }
          </div>
        </div>
        <div onClick={() => setShowMoreData(false)}>Previous</div>
      </section>
    </div>
  ) : (
    <div className="analysisMeltCurve">
      <section className="analysisMeltCurveTop">
        <div className="analysisMeltCurveTopLeft">
          <div>{isCN ? "熔解曲线" : "Melt Curve"}</div>
          <div style={{overflow: "auto"}}
               className="scrollBarStyle"
          >
            <section id="meltCurve"/>
          </div>
          <div className="autoAxes">
            <div onClick={() => setCurveAutoAxes(!curveAutoAxes)}
                 className={curveAutoAxes ? "selectedStyle" : null}/>
            {
              curveAutoAxes
                ? <div style={{width: 100}}>{isCN ? "自动坐标轴" : "Auto Axes"}</div>
                : <div>
                  <label htmlFor="Min" style={{marginLeft: 10}}> Min
                    <input id="Min" type="number"
                           value={curveMinY}
                           onChange={e => setCurveMinY(e.target.value)}
                    />
                  </label>
                  <label htmlFor="Max"> Max
                    <input id="Max" type="number"
                           value={curveMaxY}
                           onChange={e => setCurveMaxY(e.target.value)}
                    />
                  </label>
                </div>
            }
          </div>
        </div>
        <div className="analysisMeltCurveTopRight">
          <div>{isCN ? "熔解曲线峰值" : "Melt Peak"}</div>
          <div style={{overflow: "auto"}}
               className="scrollBarStyle"
          >
            <section id="meltPeak"/>
          </div>
          <div className="autoAxes">
            <div onClick={() => setPeakAutoAxes(!peakAutoAxes)}
                 className={peakAutoAxes ? "selectedStyle" : null}/>
            {
              peakAutoAxes
                ? <div style={{width: 100}}>{isCN ? "自动坐标轴" : "Auto Axes"}</div>
                : <div>
                  <label htmlFor="Min" style={{marginLeft: 10}}> Min
                    <input id="Min" type="number"
                           value={peakMinY}
                           onChange={e => setPeakMinY(e.target.value)}
                    />
                  </label>
                  <label htmlFor="Max"> Max
                    <input id="Max" type="number"
                           value={peakMaxY}
                           onChange={e => setPeakMaxY(e.target.value)}
                    />
                  </label>
                </div>
            }
          </div>
        </div>
      </section>
      <section className="analysisMeltCurveBottom">
        <PlateTable plateClass="runPagePlateTableSmall"
                    lineId={lineId}
                    setWellId={setWellId}
        />
        <div>
          <div className="analysisTargetSetting">
            <Title name={isCN ? "目标基因设置" : "View Setting"}/>
            <ul>
              <li>{isCN ? "选择" : "Opt"}</li>
              <li>{isCN ? "基因" : "Target"}</li>
              <li>{isCN ? "颜色" : "Color"}</li>
              <li>{isCN ? "通道" : "Channel"}</li>
              <li>{isCN ? "阈值" : "Threshold"}</li>
            </ul>
            <section className="scrollBarStyle">
              {
                target.map((item, index) => (
                  <ul key={item.name}>
                    <li onClick={() => viewSettingSelect(index)}
                        className={item.opt ? "selectedStyle" : ""}
                        style={{cursor: "pointer"}}
                    />
                    <li>{item.name}</li>
                    <li>
                      <div style={{backgroundColor: `${item.color}`}}/>
                    </li>
                    <li>{item.channel}</li>
                    <li/>
                  </ul>
                ))
              }
            </section>
          </div>
        </div>
        <div style={{position: "relative"}}>
          <div className="meltTableStyle scrollBarStyle">
            <ul>
              <li>{isCN ? "反应孔" : "Well"}</li>
              <li>{isCN ? "忽略" : "Omit"}</li>
              <li>{isCN ? "标记" : "Flag"}</li>
              <li>{isCN ? "样品名称" : "Sample"}</li>
              <li>{isCN ? "基因名称" : "Target"}</li>
              <li>{isCN ? "Tm1" : "Tm1"}</li>
              <li>{isCN ? "峰值" : "Peak High"}</li>
            </ul>
            <section ref={meltMessageTable} className="scrollBarStyle">
              {
                analysisShowLineArr.map((item, index) => (
                  targetSelectedArr.includes(item.target.value) && data.wells[item.id].show
                    ? <ul key={item.id + item.target.value}
                          onMouseEnter={() => messageSelected(item.id)}
                    >
                      <li>{item.well.value}</li>
                      <li>
                        <input type="checkbox" checked={JSON.parse(item.omit.value)}
                               onChange={e => changeOmit(e.target.checked, item, index)}
                        />
                      </li>
                      <li>{item.flag.value}</li>
                      <li>{item.sample.value}</li>
                      <li>{item.target.value}</li>
                      <li>{item.tm1}</li>
                      <li>{Number(item.peakHigh1).toFixed(3)}</li>
                    </ul>
                    : null
                ))
              }
            </section>
          </div>
          <ul>
            <li onClick={() => setShowMoreData(true)}>{isCN ? "更多数据" : "More Data"}</li>
          </ul>
        </div>
      </section>
    </div>
  );
});